package com.ChenYaRou.www.utils;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName JdbcUtil
 * @Description TODO
 * @Author 86183
 * @Date 2022/4/28 23:39
 * @Version 1.0
 **/
public class JdbcUtil {
    private final MyConnectionPool myConnectionPool = MyConnectionPool.getInstance();
    private  volatile static JdbcUtil jdbcUtil;

    private JdbcUtil(){}
    public static JdbcUtil getInstance(){
        if(jdbcUtil == null){
            synchronized (JdbcUtil.class){
                if(jdbcUtil == null){
                    jdbcUtil=new JdbcUtil();
                }
            }
        }
        return jdbcUtil;
    }


    /**
     * 获取对象
     * @param length 结果集的列数
     * @param metaData 结果集字段名的集合
     * @param tClass 对象的类
     * @param <T> 对象
     * @return 单个对象
     * @throws SQLException sql异常
     * @throws NoSuchFieldException 没有对应的成员变量
     * @throws InstantiationException 对象初始化异常
     * @throws IllegalAccessException 非法访问private异常
     */
    private <T> T getResultObject(int length,ResultSetMetaData metaData, Class<T> tClass,ResultSet rs) throws SQLException, NoSuchFieldException, InstantiationException, IllegalAccessException {
        T resultObject=tClass.newInstance();
        for(int i=0;i<length;i++){
            String name=metaData.getColumnName(i+1);
            Object value=rs.getObject(name);

            Field field=tClass.getDeclaredField(name);
            field.setAccessible(true);
            field.set(resultObject,value);
        }
        return resultObject;
    }


    /**
     * update和insert操作 事务改为手动
     * @param sql sql语句
     * @return 操作条数
     * @throws SQLException sql异常
     */
    public int insertOrUpdate(String sql) throws SQLException {
        Connection connection = myConnectionPool.getConnection();
        PreparedStatement ps=connection.prepareStatement(sql);
        int result = ps.executeUpdate();
        close(ps,null);
        myConnectionPool.releaseConnection(connection);
        return result;
    }

    /**
     * 多条sqk语句操作 返回操作数
     * @param sql
     * @return
     */
    public int insertOrUpdateMore(String... sql)  {
        Connection connection=myConnectionPool.getConnection();
        int i=0;
        try {
            connection.setAutoCommit(false);
            for (String s : sql) {
                if(s!=null){
                    PreparedStatement ps = connection.prepareStatement(s);
                    i += ps.executeUpdate();
                    close(ps,null);
                }
            }
            connection.commit();
            connection.setAutoCommit(true);
        } catch (SQLException e) {
            try {
                connection.rollback();
                i=0;
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            myConnectionPool.releaseConnection(connection);
        }
        return i;
    }

    /**
     * 查询出一条
     * @param sql sql语句
     * @param tClass 查询的对象类
     * @param <T> 泛型 返回任意对象
     * @return 查找啊对象
     * @throws SQLException sql异常
     * @throws InstantiationException 初始化异常
     * @throws IllegalAccessException 非法访问private异常
     * @throws NoSuchFieldException 没有对应的成员变量异常
     */
    public <T> T selectSimple(String sql,Class<T> tClass) throws SQLException, InstantiationException,
            IllegalAccessException, NoSuchFieldException {
        Connection connection = myConnectionPool.getConnection();
        PreparedStatement ps=connection.prepareStatement(sql);
        ResultSet rs = ps.executeQuery();
        T resultObject=null;

        ResultSetMetaData metaData = rs.getMetaData();
        int length = metaData.getColumnCount();

        while(rs.next()){
            resultObject = getResultObject(length, metaData, tClass,rs);
        }
        close(ps,rs);
        myConnectionPool.releaseConnection(connection);
        return resultObject;
    }

    /**
     * 查询多条对象
     * @param sql sql语句
     * @param tClass 对象所在类
     * @param <T> 对象的类
     * @return 对象的集合
     * @throws SQLException sql异常
     * @throws InstantiationException 初始化异常
     * @throws IllegalAccessException 非法访问异常
     * @throws NoSuchFieldException 没有对应的成员变量异常
     */
    public <T> List<T> selectMore(String sql, Class<T> tClass) throws SQLException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        List<T> list= new ArrayList<>();
        Connection connection = myConnectionPool.getConnection();
        PreparedStatement ps = connection.prepareStatement(sql);
        ResultSet rs = ps.executeQuery();
        ResultSetMetaData metaData= rs.getMetaData();
        int length=metaData.getColumnCount();
        while(rs.next()){
            list.add(getResultObject(length,metaData,tClass,rs));
        }
        close(ps,rs);
        myConnectionPool.releaseConnection(connection);
        return list;
    }

    /**
     * 释放rs和ps
     */
    public void close(PreparedStatement ps,ResultSet rs){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(ps!=null){
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}
